﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;

namespace zielonka.co.uk.extensions.system
{
    //Description: takes a byte[], and ints for width/height. returns a byte[] for the new image. keeps a static copy of previously provided sizes to reduce GC activity.
    /*
        public byte[] ImageResult(byte[] imageData, int width, int height) 
        {
            return imageData.Resize(width, height);      
        }
     */

    public static partial class ByteExtensions
    {
        private static readonly IList<Tuple<Rectangle, Image>> BitmapSizes = new List<Tuple<Rectangle, Image>>();
        //adapted from http://www.webcosmoforums.com/asp/321-create-high-quality-thumbnail-resize-image-dynamically-asp-net-c-code.html
        //TODO: figure out how expensive this method is
        //TODO: see if there's a way to make the IDisposable objects static
        //TODO: make sure caching is set up properly to reduce usage
        public static byte[] Resize(this byte[] source, int width, int height)
        {
            using (var image = Image.FromStream(new MemoryStream(source), true, true))
            {
                var srcWidth = image.PhysicalDimension.Width;
                var srcHeight = image.PhysicalDimension.Height;
                if (srcWidth == width && srcHeight == height)
                    return source;
                var scaleW = (double)width / srcWidth;
                var scaleH = (double)height / srcHeight;
                if (scaleW < scaleH)
                {
                    width = (int)Math.Round((scaleW * srcWidth));
                    height = (int)Math.Round((scaleW * srcHeight));
                }
                else
                {
                    width = (int)Math.Round((scaleH * srcWidth));
                    height = (int)Math.Round((scaleH * srcHeight));
                }
                var bmpTouple = BitmapSizes.FirstOrDefault(t => t.Item1.Height == height && t.Item1.Width == width);
                if (bmpTouple == null)
                {
                    bmpTouple = new Tuple<Rectangle, Image>(
                        new Rectangle(0, 0, width, height),
                        new Bitmap(width, height));
                    BitmapSizes.Add(bmpTouple);
                }
                var rect = bmpTouple.Item1;
                var bmp = bmpTouple.Item2;
                using (Graphics gr = Graphics.FromImage(bmp))
                {
                    gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                    gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                    gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
                    gr.DrawImage(image, rect);
                    using (var outStream = new MemoryStream())
                    {
                        bmp.Save(outStream, ImageFormat.Jpeg);
                        return outStream.ToArray();
                    }
                }
            }                       
        }
    }
}
